package net.pws.oos.web.mobile;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import net.pws.common.event.ApplicationEventBus;
import net.pws.common.jackson.JsonUtils;
import net.pws.common.util.DateUtils;
import net.pws.common.util.HashUtils;
import net.pws.common.util.StringUtils;
import net.pws.oos.biz.BizException;
import net.pws.oos.biz.event.TaskCompletedEventObject;
import net.pws.oos.biz.model.Area;
import net.pws.oos.biz.model.Attachment;
import net.pws.oos.biz.model.PhotoMarker;
import net.pws.oos.biz.model.Task;
import net.pws.oos.biz.query.TaskFinder;
import net.pws.oos.biz.query.parameter.TaskQueryParameter;
import net.pws.oos.biz.service.TaskService;
import net.pws.oos.security.SecurityUtils;
import net.pws.oos.web.TaskAction;
import net.pws.oos.web.dto.AttachmentDto;
import net.pws.oos.web.dto.PhotoMarkerDto;
import net.pws.oos.web.dto.TaskDto;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

@Controller
@RequestMapping("/biz/mobile/task")
@SuppressWarnings("rawtypes")
public class MobileTaskAction extends AbstractAttachementAction {
    
    private final transient Log logger = LogFactory.getLog(MobileTaskAction.class);

    @Autowired
    private TaskService taskService;

    @Autowired
    private TaskFinder taskFinder;
    
    @Autowired
    private TaskAction taskAction;

    @RequestMapping("/count.json")
    @ResponseBody
    public Object getTaskCount(TaskQueryParameter param) {
        if (param == null) {
            param = new TaskQueryParameter();
        }
        try {
            String userId = SecurityUtils.currentUserId();
            if (StringUtils.isEmpty(userId)) {
                throw new BizException("用户未登录！");
            }

            param.setExecPersonId(userId);
            return JsonUtils.succeedMap(taskFinder.countTask(param));
        } catch (Exception e) {
            logger.error(e, e);
            return JsonUtils.failedMap(e.getMessage());
        }
    }

    @RequestMapping("/list.json")
    @ResponseBody
    public Object getTaskList(TaskQueryParameter param) {
        if (param == null) {
            param = new TaskQueryParameter();
        }
        try {
            String userId = SecurityUtils.currentUserId();
            if (StringUtils.isEmpty(userId)) {
                throw new BizException("用户未登录！");
            }

            param.setExecPersonId(userId);
            List<Map> tasks = taskFinder.getTaskList(param, param.getStart(),
                    param.getLimit());
            return JsonUtils.succeedMap(tasks);
        } catch (Exception e) {
            logger.error(e, e);
            return JsonUtils.failedMap(e.getMessage());
        }
    }

    // 下发任务
    @RequestMapping("/create.json")
    @ResponseBody
    public Object createTask(TaskDto dto) {
        return taskAction.saveTask(dto);
    }

    @RequestMapping("/detail.json")
    @ResponseBody
    public Object getTaskDetail(String id) {
        if (StringUtils.isEmpty(id)) {
            return JsonUtils.failedMap("错误的参数！");
        }

        Task task = taskFinder.getTaskMap(id);
        if (task == null) {
            return JsonUtils.failedMap("您查找的任务不存在！");
        }
        TaskDto taskDto = TaskDto.from(task);

        // 获得照片信息
        List<Attachment> attachments = attachmentFinder.getPhotos(task.getId());
        if (attachments != null && attachments.size() > 0) {
            List<AttachmentDto> attDtos = AttachmentDto.from(attachments);
            for (AttachmentDto attDto : attDtos) {
                List<PhotoMarker> markers = attachmentFinder
                        .getPhotoMarkers(attDto.getId());
                attDto.setPhotoMarkers(PhotoMarkerDto.from(markers));
                filterUri(attDto);
            }
            taskDto.setAttachments(attDtos);
        }

        return JsonUtils.succeedMap(taskDto);
    }

    @RequestMapping("/start.json")
    @ResponseBody
    public Object startTask(String id) {
        if (StringUtils.isEmpty(id)) {
            return JsonUtils.failedMap("id不能为空！");
        }

        Task task = null;
        try {
            task = taskFinder.getTask(id);
        } catch (Exception e) {
            return JsonUtils.failedMap("查找任务失败！");
        }
        if (task == null) {
            return JsonUtils.failedMap("指定的任务不存在！");
        }

        if (!Task.ASSIGNED_STATUS.equals(task.getStatus())) {
            return JsonUtils.failedMap("任务的状态不正确！");
        }

        if (task.getParent() != null) {
            return JsonUtils.failedMap("不能单独开始子任务！");
        }

        String userId = SecurityUtils.currentUserId();
        if (userId == null) {
            return JsonUtils.failedMap("当前用户没有权限！");
        }
        if (!userId.equals(task.getExecutePerson().getId())) {
            return JsonUtils.failedMap("此任务不属于您！");
        }

        task = startTask(task);

        // 更改子任务状态
        // List<Task> children = taskFinder.getSubTaskList_(id);
        // List<TaskDto> childrenDto = new ArrayList<TaskDto>();
        // if (children != null) {
        // for (Task child : children) {
        // startTask(child);
        // TaskDto childDto = TaskDto.from(child);
        // childrenDto.add(childDto);
        // }
        // }
        
        task = taskFinder.getTaskMap(id);

        TaskDto dto = TaskDto.from(task);

        return JsonUtils.succeedMap(dto);
    }

    @RequestMapping("/commit.json")
    @ResponseBody
    public Object commitTask(String id) {
        if (StringUtils.isEmpty(id)) {
            return JsonUtils.failedMap("未指定对应的任务！");
        }

        Task task = taskFinder.getTask(id);
        if (task == null) {
            return JsonUtils.failedMap("对应的任务不存在！");
        }

        // 子任务不需要commit，由父任务的commit统一修改状态
        // if (task.getParent() != null) {
        // return JsonUtils.succeedJson(id);
        // }

        if (!Task.IN_PROGRESS_STATUS.equals(task.getStatus())) {
            return JsonUtils.failedMap("对应的任务状态不正确！");
        }

        try {
            // 获得子任务并标记完成
            // List<Task> children = taskFinder.getSubTaskList_(id);
            // for (int i = 0; i < children.size(); i++) {
            // completeTask(children.get(i), null);
            // }

            // 完成父任务
            completeTask(task);

            // 发送事件
            if (task.getParent() == null) {
                ApplicationEventBus.getInstance().publishEvent(
                        new TaskCompletedEventObject(id));
            }

            return JsonUtils.succeedMap(id);
        } catch (Exception e) {
            logger.error(e, e);
            return JsonUtils.failedMap(e.getMessage());
        }
    }

    // 完成任务
    private void completeTask(Task task) {
        task.setEndDate(new Date());
        task.setStatus(Task.COMPLETED_STATUS);
        if (task.getLocateDate() == null) {
            task.setLocateDate(task.getEndDate());
        }
        taskService.saveTask(task);
    }

    private Task startTask(Task task) {
        // 更新任务状态
        task.setStatus(Task.IN_PROGRESS_STATUS);
        task.setStartDate(new Date());
        task = taskService.saveTask(task);

        return task;
    }

    // 保存任务，任务提交时使用
    @RequestMapping("/save.json")
    @ResponseBody
    public Object saveTask(TaskDto dto) {
        if (StringUtils.isEmpty(dto.getId())) {
            return JsonUtils.failedMap("未指定对应的任务！");
        }

        Task task = taskFinder.getTask(dto.getId());
        if (task == null) {
            // 自主任务首次提交
            dto.setCreateDateTime(dto.getStartDate());
            dto.setAssignedDate(dto.getStartDate());
            dto.setCreatorId(SecurityUtils.currentUserId());
            dto.setExecPersonId(SecurityUtils.currentUserId());
            task = new Task();
            task = TaskDto.to(task, dto, entityManager);
            // task.setId(dto.getId());
            task.setStatus(Task.IN_PROGRESS_STATUS);
            task.setCreateType(Task.CREATE_TYPE_SELF);
            
        } else {
            if (!Task.IN_PROGRESS_STATUS.equals(task.getStatus())) {
                return JsonUtils.failedMap("对应的任务状态不正确！");
            }
        }
        task.setName(dto.getName());
        task.setDescription(dto.getDescription());
        task.setEndDate(dto.getEndDate());
        task.setLocateDate(dto.getLocateDate());
        task.setLongitude(dto.getLongitude());
        task.setLatitude(dto.getLatitude());
        task.setLocationProvice(dto.getLocationProvice());
        task.setLocationCity(dto.getLocationCity());
        task.setLocationCounty(dto.getLocationCounty());
        task.setLocationStreet(dto.getLocationStreet());
        task.setLocationNumber(dto.getLocationNumber());
        task.setLocationAddress(dto.getLocationAddress());

        task.setContent(dto.getDescription());
        task.setPlanEndDate(dto.getPlanEndDate());
        task.setPlanLongitude(dto.getLongitude());
        task.setPlanLatitude(dto.getLatitude());
        if(StringUtils.isNotBlank(dto.getLocationCity())){
        	Map<String, String> parameters = new HashMap<String, String>();
        	parameters.put("name", dto.getLocationCity());
			Area area = (Area) entityManager.findFirst("from Area a where a.name=:name and a.parent is null", parameters );
        	task.setArea(area);
        }
        if(StringUtils.isNotBlank(dto.getLocationCounty()) && task.getArea() != null){
        	Map<String, String> parameters = new HashMap<String, String>();
        	parameters.put("name", dto.getLocationCounty());
        	parameters.put("parent", task.getArea().getId());
        	Area county = (Area) entityManager.findFirst("from Area a where a.name=:name and a.parent.id = :parent", parameters );
        	task.setCounty(county);
        }
        task.setTowns(dto.getLocationStreet());
        
        removeBadAddress(task);

        try {
            taskService.saveTask(task);
            return JsonUtils.succeedMap(task.getId());
        } catch (Exception e) {
            logger.error(e, e);
            return JsonUtils.failedMap(e.getMessage());
        }
    }

    @RequestMapping("/attachment/upload.json")
    @ResponseBody
    public Object uploadTaskAttachment(HttpServletRequest request,
            AttachmentDto dto) {
        try {
            return doUpload(dto);
        }
        catch (Exception e) {
            logger.error(e, e);
            return JsonUtils.failedMap(e.getMessage());
        }
    }

    private Object doUpload(AttachmentDto dto) {
        if (StringUtils.isEmpty(dto.getResourceId())) {
            return JsonUtils.failedMap("未指定对应的任务！");
        }

        MultipartFile file = dto.getFile();
        if (file == null || file.getSize() <= 0) {
            return JsonUtils.failedMap("上传的附件大小不正确！");
        }

        Task task = taskFinder.getTask(dto.getResourceId());
        if(task == null) {
            return JsonUtils.failedMap("未找到对应的任务！");
        }

        // 根据MD5判断图片是否存在
        String checkCode = dto.getCheckCode();
        if (StringUtils.isBlank(checkCode)) {
            return JsonUtils.failedMap("上传的文件被破坏！");
        }
        Attachment attachment = attachmentFinder.getAttachment(checkCode,
                task.getId());
        if (null != attachment) {
            // 图片已存在
            // 处理标记
            List<PhotoMarker> markers = getMarkers(dto.getJson());
            attachmentService.updatePhotoMarkers(attachment, markers);

            return JsonUtils.succeedMap(AttachmentDto.from(attachment));
        }

        // 检查上传的文件的校验码与提交的校验码是否一致
        String fileHash = null;
        try {
            fileHash = HashUtils.getHash(file.getInputStream(), "MD5");
        } catch (Exception e) {
            logger.error(e, e);
            return JsonUtils.failedMap("上传的文件被破坏！");
        }
        if (!checkCode.equals(fileHash)) {
            return JsonUtils.failedMap("上传的文件被破坏！");
        }

        // 保存附件到文件系统
        try {
            attachment = storeAttachment(dto, task);
        } catch (Exception e) {
            logger.error(e, e);
            return JsonUtils.failedMap(e.getMessage());
        }

        return JsonUtils.succeedMap(AttachmentDto.from(attachment));
    }

    
    // ========================================================
    // =================== 营销版本临时 =======================

    @RequestMapping("/demo/count.json")
    @ResponseBody
    public Object countDemo(TaskQueryParameter param) {
        param = initParametersByRole(param);
        try {
            if (param.getLocateStartDate() == null
                    || param.getLocateEndDate() == null) {
                String dateStr = DateUtils.getDateStr(new Date());
                Date today = DateUtils.parseDate(dateStr);
                param.setLocateStartDate(today);
                param.setLocateEndDate(today);
            }
            return JsonUtils.succeedMap(taskFinder.countBySaleDemo(param));
        } catch (Exception e) {
            logger.error(e, e);
            return JsonUtils.failedMap(e.getMessage());
        }
    }

    @RequestMapping("/demo/list.json")
    @ResponseBody
    public Object listDemo(TaskQueryParameter param) {
        param = initParametersByRole(param);
        try {
            if (param.getLocateStartDate() == null
                    || param.getLocateEndDate() == null) {
                String dateStr = DateUtils.getDateStr(new Date());
                Date today = DateUtils.parseDate(dateStr);
                param.setLocateStartDate(today);
                param.setLocateEndDate(today);
            }
            List<Map> tasks = taskFinder.listBySaleDemo(param);
            return JsonUtils.succeedMap(tasks);
        } catch (Exception e) {
            logger.error(e, e);
            return JsonUtils.failedMap(e.getMessage());
        }
    }

    private TaskQueryParameter initParametersByRole(TaskQueryParameter param) {
        if (param == null) {
            param = new TaskQueryParameter();
        }

        if (StringUtils.areBlank(param.getExecPersonId(),
                param.getExecOrganId())) {
            if (SecurityUtils.isManager()) {
                param.setExecOrganId(SecurityUtils.currentUser().getOrganId());
            } else {
                param.setExecPersonId(SecurityUtils.currentUserId());
            }
        }
        return param;
    }

    private void removeBadAddress(Task task) {
        if (task == null || StringUtils.isBlank(task.getLocationAddress())) {
            return;
        }
        
        if (StringUtils.hasChineseChar(task.getLocationAddress())) {
            return;
        }
        
        task.setLocationProvice(null);
        task.setLocationCity(null);
        task.setLocationCounty(null);
        task.setLocationStreet(null);
        task.setLocationNumber(null);
        task.setLocationAddress(null);
    }
    
}
